#!/bin/bash

# sealos一键在线安装脚本

# 检查是否为root用户
if [ "$(id -u)" != "0" ]; then
    echo "错误: 请使用root用户运行此脚本"
    exit 1
fi

# 配置YUM源
configure_yum_repo() {
    echo "[INFO] 正在配置YUM源..."
    local repo_file="/etc/yum.repos.d/fury.repo"
    local repo_content="[fury]\nname=Gemfury Private Repo\nbaseurl=https://yum.fury.io/labring/\nenabled=1\ngpgcheck=0"
    
    if [ -f "$repo_file" ]; then
        echo "[INFO] fury.repo已存在，跳过配置"
        return 0
    fi
    
    echo -e "$repo_content" > "$repo_file"
    if [ $? -ne 0 ]; then
        echo "[ERROR] 无法创建YUM源配置文件"
        return 1
    fi
    
    echo "[INFO] YUM源配置完成"
}

# 从YUM源安装sealos
install_sealos_from_yum() {
    echo "[INFO] 正在从YUM源安装sealos..."
    
    if ! command -v sealos &> /dev/null; then
        if command -v yum &> /dev/null; then
            yum install -y sealos
        elif command -v dnf &> /dev/null; then
            dnf install -y sealos
        else
            echo "错误: 无法识别的包管理器，请手动安装sealos"
            return 1
        fi
        
        if [ $? -ne 0 ]; then
            echo "错误: sealos安装失败"
            return 1
        fi
    fi
    
    echo "[INFO] sealos安装完成"
}

# 检查并安装sshpass
check_and_install_sshpass() {
    echo "[INFO] 检查sshpass是否已安装..."
    if ! command -v sshpass &> /dev/null; then
        echo "[INFO] 正在安装sshpass..."
        if command -v apt-get &> /dev/null; then
            apt-get update && apt-get install -y sshpass
        elif command -v yum &> /dev/null; then
            yum install -y sshpass
        elif command -v dnf &> /dev/null; then
            dnf install -y sshpass
        else
            echo "错误: 无法识别的包管理器，请手动安装sshpass"
            exit 1
        fi
        
        if [ $? -ne 0 ]; then
            echo "错误: sshpass安装失败"
            exit 1
        fi
    fi
    echo "[INFO] sshpass已安装"
}

# 读取配置文件
# 读取配置文件
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/config.ini"
echo "[DEBUG] 初始配置文件路径: $CONFIG_FILE"
if [ -f "$CONFIG_FILE" ]; then
    echo "[DEBUG] 开始读取基础配置项"
    K8S_VERSION=$(grep -E '^K8S_VERSION\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
    SEALOS_URL=$(grep -E '^SEALOS_URL\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
    HELM_VERSION=$(grep -E '^HELM_VERSION\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
    CALICO_VERSION=$(grep -E '^CALICO_VERSION\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
    DEBUG_MODE=$(grep -E '^DEBUG_MODE\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
    echo "[DEBUG] 基础配置读取完成: K8S_VERSION=$K8S_VERSION, DEBUG_MODE=$DEBUG_MODE"
fi

# 参数解析
while getopts "v:d" opt; do
    case $opt in
        v) K8S_VERSION="$OPTARG" ;;
        d) DEBUG_MODE="true" ;;
        *) echo "用法: $0 [-v k8s版本] [-d 调试模式]" ; exit 1 ;;
    esac
done <<< "$nodes_info"

# 设置默认k8s版本
K8S_VERSION=${K8S_VERSION:-"v1.25.0"}
DEBUG_MODE=${DEBUG_MODE:-true}

# 获取本机IP地址
get_local_ip() {
    if command -v ip &> /dev/null; then
        ip addr show | grep -E 'inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -n 1
    elif command -v ifconfig &> /dev/null; then
        ifconfig | grep -E 'inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v '127.0.0.1' | awk '{print $2}' | head -n 1
    else
        echo "错误: 无法获取本机IP地址"
        return 1
    fi
}

# 修改hostname函数
modify_hostname() {
    # 打印传入的节点信息，带上函数名
    echo "[DEBUG] modify_hostname传入的节点信息: $1"
    local nodes_info=$1
    echo "[INFO] 正在修改节点hostname..."
    
    if [ -n "$nodes_info" ]; then
        # 获取本机IP
        local local_ip=$(get_local_ip)
        if [ $? -ne 0 ]; then
            echo "[ERROR] 获取本机IP地址失败"
            return 1
        fi
        
        # 处理传入的节点信息
        # 处理传入的节点信息
        IFS=',' read -ra NODES <<< "$nodes_info"
        # 打印NODES数组的内容
        echo "[DEBUG] NODES数组内容: ${NODES[@]}"
        for node in "${NODES[@]}"; do
            # 打印node
            echo "[DEBUG] 处理节点 $node"

           
            local node_name=${node%%=*}
            local remaining=${node#*=}
            local ip=${remaining%%=*}
            local user_pass=${remaining#*=}
            local user=${user_pass%%:*}
            local password=${user_pass#*:}
            
            # 打印上面获取到的值
            echo "[DEBUG] 节点信息: node_name=$node_name, ip=$ip, user=$user, password=$password"
            echo "[INFO] 正在修改节点 $ip 的hostname为 $node_name"
            
            # 判断是否为本机IP
            if [ "$ip" = "$local_ip" ]; then
                echo "[INFO] 检测到本机IP，直接修改hostname"
                if hostnamectl set-hostname "$node_name"; then
                    echo "[INFO] 本机hostname修改成功"
                else
                    echo "[ERROR] 本机hostname修改失败"
                    return 1
                fi
            else
                # 远程节点修改hostname
                echo "[DEBUG] 尝试SSH连接到 $user@$ip"
                echo "[DEBUG] 执行命令: sshpass -p '******' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ConnectionAttempts=3 -o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes $user@$ip 'hostnamectl set-hostname $node_name'"
                if ! sshpass -p "$password" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ConnectionAttempts=3 -o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes "$user@$ip" \
                    "hostnamectl set-hostname $node_name" 2>/tmp/ssh_error >/tmp/ssh_output; then
                    error_msg=$(cat /tmp/ssh_error)
                    output_msg=$(cat /tmp/ssh_output)
                    echo "[ERROR] 节点 $ip hostname修改失败"
                else
                    echo "[INFO] 节点 $ip hostname修改成功"
                fi
            fi
           


        done
    fi
    
    echo "[INFO] hostname修改完成"
}

# 更新hosts文件函数
update_hosts_file() {
    # 打印传入的节点信息
    echo "[DEBUG] update_hosts_file传入的节点信息: $1"
    local nodes_info=$1
    echo "[INFO] 正在更新/etc/hosts文件..."
    
    if [ -n "$nodes_info" ]; then
        # 获取本机IP
        local local_ip=$(get_local_ip)
        if [ $? -ne 0 ]; then
            echo "[ERROR] 获取本机IP地址失败"
            return 1
        fi
        
        # 生成新的hosts内容
        local hosts_content="# Kubernetes nodes start\n"
        IFS=',' read -ra NODES <<< "$nodes_info"
        for node in "${NODES[@]}"; do
            local node_name=${node%%=*}
            local remaining=${node#*=}
            local ip=${remaining%%=*}
            local user_pass=${remaining#*=}
            local user=${user_pass%%:*}
            local password=${user_pass#*:*}
            
            echo "[DEBUG] 节点信息: node_name=$node_name, ip=$ip"
            hosts_content+="$ip $node_name\n"
        done
        hosts_content+="# Kubernetes nodes end\n"
        
        # 遍历所有节点进行更新
        for node in "${NODES[@]}"; do
            local node_name=${node%%=*}
            local remaining=${node#*=}
            local ip=${remaining%%=*}
            local user_pass=${remaining#*=}
            local user=${user_pass%%:*}
            local password=${user_pass#*:*}
            
            if [ "$ip" = "$local_ip" ]; then
                echo "[INFO] 更新本机hosts文件"
                # 备份本机hosts文件
                cp /etc/hosts /etc/hosts.bak
                # 清除原有配置并添加新配置
                sed -i '/# Kubernetes nodes start/,/# Kubernetes nodes end/d' /etc/hosts
                echo -e "$hosts_content" >> /etc/hosts
                echo "[INFO] 本机hosts文件更新完成"
            else
                echo "[INFO] 更新远程节点 $ip 的hosts文件"
                # 通过SSH更新远程节点的hosts文件
                echo "[DEBUG] 尝试SSH连接到 $user@$ip"
                if ! sshpass -p "$password" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ConnectionAttempts=3 \
                    -o PreferredAuthentications=password -o PubkeyAuthentication=no -o PasswordAuthentication=yes "$user@$ip" \
                    "cp /etc/hosts /etc/hosts.bak && \
                    sed -i '/# Kubernetes nodes start/,/# Kubernetes nodes end/d' /etc/hosts && \
                    echo -e \"$hosts_content\" >> /etc/hosts" 2>/tmp/ssh_error >/tmp/ssh_output; then
                    error_msg=$(cat /tmp/ssh_error)
                    output_msg=$(cat /tmp/ssh_output)
                    echo "[ERROR] 节点 $ip hosts文件更新失败"
                    echo "[ERROR] 错误信息: $error_msg"
                    echo "[ERROR] 输出信息: $output_msg"
                    return 1
                else
                    echo "[INFO] 节点 $ip hosts文件更新完成"
                fi
            fi
        done
    else
        echo "[WARNING] 未提供节点信息，跳过hosts文件更新"
    fi
}


# 安装sealos函数
install_sealos() {
    echo "[INFO] 正在安装sealos..."
    
    if ! command -v sealos &> /dev/null; then
        if [ "$ONLINE_MODE" = "true" ]; then
            wget ${SEALOS_URL} \
                && tar -zxvf $(basename "$SEALOS_URL") sealos \
                && chmod +x sealos \
                && mv sealos /usr/bin/sealos \
                && rm -rf $(basename "$SEALOS_URL")
        else
            cp "$OFFLINE_PATH/$(basename "$SEALOS_URL")" . \
                && tar -zxvf $(basename "$SEALOS_URL") sealos \
                && chmod +x sealos \
                && mv sealos /usr/bin/sealos
        fi
        
        if [ $? -ne 0 ]; then
            echo "错误: sealos安装失败"
            exit 1
        fi
    fi
    
    echo "[INFO] sealos安装完成"
}

# 安装k8s集群函数
install_k8s() {
    local masters="$1"
    local nodes="$2"
    local deploy_mode="$3"
    
    echo "[INFO] 正在安装Kubernetes ${K8S_VERSION}..."
    
    if [ "$deploy_mode" = "single" ]; then
        local deploy_flag="--single"
    else
        if [ -n "$masters" ]; then
            deploy_flag="--masters $masters"
            if [ -n "$nodes" ]; then
                deploy_flag="$deploy_flag --nodes $nodes"
            fi
        else
            deploy_flag="--nodes $nodes"
        fi
    fi
    
    if [ "$ONLINE_MODE" = "true" ]; then
        if [ "$DEBUG_MODE" = "true" ]; then
            echo "[DEBUG] 调试模式已启用，显示详细安装信息"
            sealos run --debug labring/kubernetes:${K8S_VERSION} \
                labring/helm:${HELM_VERSION:-v3.8.2} \
                labring/calico:${CALICO_VERSION:-v3.24.1} \
                $deploy_flag
        else
            sealos run labring/kubernetes:${K8S_VERSION} \
                labring/helm:${HELM_VERSION:-v3.8.2} \
                labring/calico:${CALICO_VERSION:-v3.24.1} \
                $deploy_flag
        fi
    else
        sealos run "$OFFLINE_PATH/kubernetes:${K8S_VERSION}" \
            "$OFFLINE_PATH/helm:${HELM_VERSION:-v3.8.2}" \
            "$OFFLINE_PATH/calico:${CALICO_VERSION:-v3.24.1}" \
            $deploy_flag
    fi
    
    if [ $? -ne 0 ]; then
        echo "错误: Kubernetes安装失败"
        exit 1
    fi
    
    echo "[INFO] Kubernetes安装完成"
}

# 主流程
main() {
    # 读取安装模式配置
    echo "[DEBUG] 检查配置文件是否存在: $CONFIG_FILE"
    if [ -f "$CONFIG_FILE" ]; then
        echo "[DEBUG] 配置文件存在，开始读取配置"
        ONLINE_MODE=$(grep -E '^ONLINE_MODE\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
        OFFLINE_PATH=$(grep -E '^OFFLINE_PATH\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
        DEPLOY_MODE=$(grep -E '^DEPLOY_MODE\s*=' "$CONFIG_FILE" | cut -d= -f2 | tr -d ' ')
        
        echo "[DEBUG] 读取到配置: ONLINE_MODE=$ONLINE_MODE, OFFLINE_PATH=$OFFLINE_PATH, DEPLOY_MODE=$DEPLOY_MODE"
        
        # 读取多节点配置
        if [ "$DEPLOY_MODE" = "multi" ]; then
            # 读取[NODES]区块下的所有节点配置
            echo "[DEBUG] 开始读取[NODES]区块下的节点配置"
            MASTERS=""
            NODES=""
            in_nodes_section=false
            while IFS= read -r line; do
                # 去除行首尾的空白字符
                line=$(echo "$line" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
                
                # 跳过空行和注释行
                [[ -z "$line" || "$line" =~ ^# ]] && continue
                
                # 检查是否进入或离开[NODES]区块
                if [[ "$line" == "[NODES]" ]]; then
                    in_nodes_section=true
                    continue
                elif [[ "$line" =~ ^\[.*\]$ && "$line" != "[NODES]" ]]; then
                    in_nodes_section=false
                    continue
                fi
                
                # 处理[NODES]区块中的节点配置
                if [ "$in_nodes_section" = true ] && [[ "$line" =~ ^(master|node)[0-9]+= ]]; then
                    echo "[DEBUG] 读取到节点配置行: $line"
                    if [[ "$line" =~ ^master ]]; then
                        MASTERS="${MASTERS}${line},"
                    elif [[ "$line" =~ ^node ]]; then
                        NODES="${NODES}${line},"
                    fi
                fi
            done < "$CONFIG_FILE"
            
            # 移除最后的逗号
            MASTERS=$(echo "$MASTERS" | sed 's/,$//')
            NODES=$(echo "$NODES" | sed 's/,$//')
            
            echo "[DEBUG] 读取到节点配置:"
            echo "[DEBUG] Master节点: $MASTERS"
            echo "[DEBUG] Node节点: $NODES"
            
            if [ -n "$MASTERS" ]; then
                deploy_flag="--masters $MASTERS"
                if [ -n "$NODES" ]; then
                    deploy_flag="$deploy_flag --nodes $NODES"
                fi
            else
                deploy_flag="--nodes $NODES"
            fi
        fi
    else
        echo "[DEBUG] 配置文件不存在，使用默认配置"
        # 设置默认安装模式为在线安装，这样可以直接从网络下载所需组件
        ONLINE_MODE="true"
        # 设置默认部署模式为单节点模式，适合快速测试和开发环境
        DEPLOY_MODE="single"
        # 使用单节点部署标志，将在本机上部署一个all-in-one的Kubernetes集群
        deploy_flag="--single"
    fi


      
    check_and_install_sshpass
    
  
    
    # 合并所有节点信息，确保不重复
    local ALL_NODES=""
    if [ -n "$MASTERS" ]; then
        ALL_NODES="$MASTERS"
        if [ -n "$NODES" ]; then
            ALL_NODES="$ALL_NODES,$NODES"
        fi
    elif [ -n "$NODES" ]; then
        ALL_NODES="$NODES"
    fi
    
    modify_hostname "$ALL_NODES"
    update_hosts_file "$ALL_NODES"
    
    # install_sealos

    # 配置YUM源
    configure_yum_repo
    
    # 从YUM源安装sealos
    install_sealos_from_yum
    
    return 0
    install_k8s "$MASTERS" "$NODES" "$DEPLOY_MODE"
    
    echo "[SUCCESS] Kubernetes ${K8S_VERSION} 安装完成!"
    echo "运行 'kubectl get nodes' 查看集群状态"
}

main